﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
using System.Drawing.Drawing2D;

namespace nsGumController
{
    public partial class DockMain : DockContent
    {
        private CLog mLog = CGumController.mLog;
        private Pen pen;
        private float divisor = 1;      // 用于缩小输入坐标的除数，以在面板中显示完整的图形

        public DockMain()
        {
            InitializeComponent();
            ResetPen();
        }

        private void DockMain_Load(object sender, EventArgs e)
        {
            
        }

        private string GetCylinderStateFromByte(byte bt)
        {
            string res = "";
            switch (bt)
            {
                case 0:
                    res = "停止";
                    break;

                case 1:
                    res = "伸出中";
                    break;

                case 2:
                    res = "拉回中";
                    break;

                case 3:
                    res = "伸出";
                    break;

                case 4:
                    res = "拉回";
                    break;

                default:
                    res = "未知";
                    break;
            }
            return res;
        }

        private string GetMotorStateFromByte(byte bt)
        {
            string res = "";
            switch (bt)
            {
                case 0:
                    res = "停止";
                    break;

                case 1:
                    res = "正向";
                    break;

                case 2:
                    res = "负向";
                    break;

                case 3:
                    res = "异常";
                    break;

                default:
                    res = "未知";
                    break;
            }
            return res;
        }

        /// <summary>
        /// 将控制板返回的信息显示到主界面上
        /// </summary>
        public void ShowMashineInfo()
        {
            txtCoordinateX.Text = CGumController.mMashineInfo.x.ToString();
            txtCoordinateY.Text = CGumController.mMashineInfo.y.ToString();
            txtOriginX.Text = CGumController.mMashineInfo.originX.ToString();
            txtOriginY.Text = CGumController.mMashineInfo.originY.ToString();
            txtStatL.Text = GetMotorStateFromByte(CGumController.mMashineInfo.statLineMotor);
            txtStatC1.Text = GetCylinderStateFromByte(CGumController.mMashineInfo.statC1);
            txtStatC2.Text = GetCylinderStateFromByte(CGumController.mMashineInfo.statC2);
            txtStatC3.Text = GetCylinderStateFromByte(CGumController.mMashineInfo.statC3);
            txtStatCz.Text = GetCylinderStateFromByte(CGumController.mMashineInfo.statCz);
            txtGumState.Text = CGumController.mMashineInfo.statGumPointer == 0 ? "关闭" : "打开";
            txtStatX.Text = GetMotorStateFromByte(CGumController.mMashineInfo.statX);
            txtStatY.Text = GetMotorStateFromByte(CGumController.mMashineInfo.statY);
            txtRunningState.Text = CGumController.mMashineInfo.iRunningFlag == 0 ? "停止" : "运行";
            txtPauseState.Text = CGumController.mMashineInfo.iPausedFlag == 0 ? "继续" : "暂停";
            txtIsProcessing.Text = CGumController.mMashineInfo.iProcessingFlag == 0 ? "无" : "有";
            txtBoardCount.Text = mBoardCount.ToString();
            int index = CGumController.mMashineInfo.currentStep;
            if (index >= 0 && index < CGumController.mDockSetParameter.dgvAutoGumList.Rows.Count
                && CGumController.mMashineInfo.iRunningFlag == 1)
            {
                CGumController.mDockSetParameter.dgvAutoGumList.ClearSelection();
                CGumController.mDockSetParameter.dgvAutoGumList.Rows[index].Selected = true;
                CGumController.mDockSetParameter.dgvAutoGumList.CurrentCell = CGumController.mDockSetParameter.dgvAutoGumList.SelectedCells[0];
            }
        }

        private void btnDoAutoGumActions_Click(object sender, EventArgs e)
        {
            CGumController.mDockSetParameter.SendAllPararmeter();
        }

        private void btnAutoGumStop_Click(object sender, EventArgs e)
        {
            GumCommandStop();
        }

        private void btnAutoGumBegin_Click(object sender, EventArgs e)
        {
            GumCommandStart();
        }

        private void btnAutoGumPause_Click(object sender, EventArgs e)
        {
            if (btnAutoGumPause.Text == "暂停")
            {
                GumCommandPause();
                btnAutoGumPause.Text = "继续";
                btnAutoGumPause.Image = Properties.Resources.resume;
            }
            else
            {
                GumCommandResume();
                btnAutoGumPause.Text = "暂停";
                btnAutoGumPause.Image = Properties.Resources.pause;
            }
        }

        private void btnAutoGumAbord_Click(object sender, EventArgs e)
        {
            GumCommandAbord();
        }

        private void btnSysReset_Click(object sender, EventArgs e)
        {
            SysRestCommand(1);
        }

        private void EnQueueSend(ET_GPES_SENDMSG stSend)
        {
            CGumController.mDockSerialProtocol.EnQueueSend(stSend);
        }
        
        /// <summary>
        /// 点胶枪控制命令
        /// </summary>
        /// <param name="bt">
        /// 0：停止
        /// 1：开始
        /// 2：暂停
        /// 3：继续
        /// 4：取消
        /// </param>
        private void GumCommandStart()
        {
            ET_GPES_SENDMSG stSend = new ET_GPES_SENDMSG();
            stSend.CLA = (byte)CLA.CLA_CTRL;
            stSend.INS = (byte)INS.CMD_START;
            stSend.sendMsg = new byte[1] { 1 };
            EnQueueSend(stSend);
        }

        private void GumCommandPause()
        {
            ET_GPES_SENDMSG stSend = new ET_GPES_SENDMSG();
            stSend.CLA = (byte)CLA.CLA_CTRL;
            stSend.INS = (byte)INS.CMD_PAUSE;
            stSend.sendMsg = new byte[1] { 1 };
            EnQueueSend(stSend);
        }

        private void GumCommandResume()
        {
            ET_GPES_SENDMSG stSend = new ET_GPES_SENDMSG();
            stSend.CLA = (byte)CLA.CLA_CTRL;
            stSend.INS = (byte)INS.CMD_RESUME;
            stSend.sendMsg = new byte[1] { 1 };
            EnQueueSend(stSend);
        }

        private void GumCommandAbord()
        {
            ET_GPES_SENDMSG stSend = new ET_GPES_SENDMSG();
            stSend.CLA = (byte)CLA.CLA_CTRL;
            stSend.INS = (byte)INS.CMD_ABORD;
            stSend.sendMsg = new byte[1] { 1 };
            EnQueueSend(stSend);
        }

        private void GumCommandStop()
        {
            ET_GPES_SENDMSG stSend = new ET_GPES_SENDMSG();
            stSend.CLA = (byte)CLA.CLA_CTRL;
            stSend.INS = (byte)INS.CMD_STOP;
            stSend.sendMsg = new byte[1] { 1 };
            EnQueueSend(stSend);
        }

        private void SysRestCommand(byte command)
        {
            ET_GPES_SENDMSG stSend = new ET_GPES_SENDMSG();
            stSend.CLA = (byte)CLA.CLA_CTRL;
            stSend.INS = (byte)INS.CMD_RESET;
            stSend.sendMsg = new byte[1] { command };
            EnQueueSend(stSend);
        }

        private void chkIsBeginQuery_CheckedChanged(object sender, EventArgs e)
        {
            if (chkIsBeginQuery.Checked)
            {
                CGumController.mDockSerialProtocol.BeginQueryThread();
            }
            else
            {
                CGumController.mDockSerialProtocol.AbordQueryThread();
            }
        }

        private void txtCoordinateX_TextChanged(object sender, EventArgs e)
        {
            drawArea.SetCurrentPoint((int)((CGumController.mMashineInfo.x + CGumController.mMashineInfo.originX) / divisor), (int)((CGumController.mMashineInfo.y + CGumController.mMashineInfo.originY) / divisor));
            DrawAction();
        }

        private void txtCoordinateY_TextChanged(object sender, EventArgs e)
        {
            drawArea.SetCurrentPoint((int)((CGumController.mMashineInfo.x + CGumController.mMashineInfo.originX) / divisor), (int)((CGumController.mMashineInfo.y + CGumController.mMashineInfo.originY) / divisor));
            DrawAction();
        }

        private void drawArea_SizeChanged(object sender, EventArgs e)
        {
            DrawAction();
        }

        private void ResetPen()
        {
            if (pen == null)
            {
                pen = new Pen(Color.Black, 2);
            }
            else
            {
                pen.Color = Color.Black;
                pen.Width = 2;
            }
            pen.DashStyle = DashStyle.Dash;
            pen.StartCap = LineCap.NoAnchor;
            pen.EndCap = LineCap.ArrowAnchor;
        }

        /// <summary>
        /// 将Actions中的动作绘制的DrawArea上
        ///  非插补移动用虚线，插补移动用实线
        ///  点胶开启使用黄色 Z轴压下线条宽度加倍
        ///  绿色圆圈为原点位置
        /// </summary>
        public void DrawAction()
        {
            int actionCount = CGumController.mDockSetParameter.mAutoActionList.Count;

            if (drawArea.drawList != null)
            {
                drawArea.drawList.Clear();
            }

            ResetPen();
            CalculateDivisor();
            if (divisor == 0)
            {
                return; // 窗口在AutoHide状态，该值可能为0
            }

            float originX = CGumController.mDockSetParameter.originXSet;
            float originY = CGumController.mDockSetParameter.originYSet;
            float x1 = originX;
            float y1 = originY;
            float x2 = originX;
            float y2 = originY;
            Line line;
            Arc arc;
            int radius;

            // 绘制原点
            Pen penTemp = new Pen(Color.Green, 1);
            penTemp.DashStyle = DashStyle.Solid;
            radius = Math.Min(drawArea.Size.Width, drawArea.Size.Height) / 35;
            Circle circle = new Circle(new PointF(originX / divisor, originY / divisor), radius, Color.Green, penTemp);
            drawArea.AddToDrawList(circle);

            // 绘制动作
            foreach (ActionParas action in CGumController.mDockSetParameter.mAutoActionList)
            {
                switch (action.Cmd)
                {
                    case GUM_ACTION.移动到:
                        x2 = action.Point1X + originX;
                        y2 = action.Point1Y + originY;
                        pen.DashStyle = DashStyle.Dash;
                        line = new Line(x1 / divisor, y1 / divisor, x2 / divisor, y2 / divisor, pen);
                        drawArea.AddToDrawList(line);
                        x1 = x2;
                        y1 = y2;
                        break;

                    case GUM_ACTION.画圆弧:
                        // 先画一条到圆弧起点的直线
                        float startX;
                        float startY;
                        float endX;
                        float endY;
                        AnalyseMode(action, out startX, out startY, out endX, out endY);
                        pen.DashStyle = DashStyle.Dash;
                        line = new Line(x1 / divisor, y1 / divisor, startX / divisor, startY / divisor, pen);
                        drawArea.AddToDrawList(line);
                        x1 = endX;
                        y1 = endY;

                        float startAngel = 0;
                        float endAngel = 90;
                        Pen penTemp1 = (Pen)pen.Clone();
                        if (action.Mode <= 4)
                        {
                            startAngel = (action.Mode - 1) * 90;
                            penTemp1.EndCap = LineCap.NoAnchor;
                            penTemp1.StartCap = LineCap.ArrowAnchor;
                        }
                        else
                        {
                            startAngel = (action.Mode - 5) * 90;
                            penTemp1.EndCap = LineCap.ArrowAnchor;
                            penTemp1.StartCap = LineCap.NoAnchor;
                        }
                        endAngel = 90;
                        radius = action.Radius;
                        penTemp1.DashStyle = DashStyle.Solid;
                        arc = new Arc(new PointF((action.Point1X+originX) / divisor, (action.Point1Y+originY) / divisor), radius / divisor, startAngel, endAngel, penTemp1);
                        drawArea.AddToDrawList(arc);
                        break;

                    case GUM_ACTION.画直线:
                        // 先画一条到直线起点的直线
                        x2 = action.Point1X + originX;
                        y2 = action.Point1Y + originY;
                        pen.DashStyle = DashStyle.Dash;
                        line = new Line(x1 / divisor, y1 / divisor, x2 / divisor, y2 / divisor, pen);
                        drawArea.AddToDrawList(line);

                        x1 = action.Point1X + originX;
                        y1 = action.Point1Y + originY;
                        x2 = action.Point2X + originX;
                        y2 = action.Point2Y + originY;
                        pen.DashStyle = DashStyle.Solid;
                        line = new Line(x1 / divisor, y1 / divisor, x2 / divisor, y2 / divisor, pen);
                        drawArea.AddToDrawList(line);
                        x1 = x2;
                        y1 = y2;
                        break; ;

                    case GUM_ACTION.点胶开:
                        pen.Color = Color.Orange;
                        pen.DashStyle = DashStyle.Solid;
                        break;

                    case GUM_ACTION.点胶关:
                        pen.Color = Color.Black;
                        pen.DashStyle = DashStyle.Dash;
                        break;

                    case GUM_ACTION.Z轴压下:
                        pen.Width = 4;
                        break;

                    case GUM_ACTION.Z轴抬起:
                        pen.Width = 2;
                        break;

                    default:
                        break;
                }
            }

            Invalidate(true);
        }

        private void AnalyseMode(ActionParas action, out float startX, out float startY, out float endX, out float endY)
        {
            switch (action.Mode)
            {
                case 1:
                    startX = action.Point1X;
                    startY = action.Point1Y + action.Radius;
                    endX = action.Point1X + action.Radius;
                    endY = action.Point1Y;
                    break;
                case 2:
                    startX = action.Point1X - action.Radius;
                    startY = action.Point1Y;
                    endX = action.Point1X;
                    endY = action.Point1Y + action.Radius;
                    break;
                case 3:
                    startX = action.Point1X;
                    startY = action.Point1Y - action.Radius;
                    endX = action.Point1X - action.Radius;
                    endY = action.Point1Y;
                    break;
                case 4:
                    startX = action.Point1X + action.Radius;
                    startY = action.Point1Y;
                    endX = action.Point1X;
                    endY = action.Point1Y - action.Radius;
                    break;
                case 5:
                    startX = action.Point1X + action.Radius;
                    startY = action.Point1Y;
                    endX = action.Point1X;
                    endY = action.Point1Y + action.Radius;
                    break;
                case 6:
                    startX = action.Point1X;
                    startY = action.Point1Y + action.Radius;
                    endX = action.Point1X - action.Radius;
                    endY = action.Point1Y;
                    break;
                case 7:
                    startX = action.Point1X - action.Radius;
                    startY = action.Point1Y;
                    endX = action.Point1X;
                    endY = action.Point1Y - action.Radius;
                    break;
                case 8:
                    startX = action.Point1X;
                    startY = action.Point1Y - action.Radius;
                    endX = action.Point1X + action.Radius;
                    endY = action.Point1Y;
                    break;
                default:
                    startX = action.Point1X;
                    startY = action.Point1Y;
                    endX = action.Point1X;
                    endY = action.Point1Y;
                    break;
            }
            startX += CGumController.mMashineInfo.originX;
            startY += CGumController.mMashineInfo.originY;
            endX += CGumController.mMashineInfo.originX;
            endY += CGumController.mMashineInfo.originY;
        }

        /// <summary>
        /// 计算divisor，该值是用于将输入坐标缩小，以在面板中显示完整的图形
        /// </summary>
        private void CalculateDivisor()
        {
            float div = 1;
            int padding = 10;
            int originX = CGumController.mDockSetParameter.originXSet;
            int originY = CGumController.mDockSetParameter.originYSet;
            int maxX = originX + padding;
            int maxY = originY + padding;
            CalculateDivisor(maxX, maxY, ref div);

            foreach (ActionParas action in CGumController.mDockSetParameter.mAutoActionList)
            {
                if (action.Cmd == GUM_ACTION.移动到)
                {
                    maxX = action.Point1X;
                    maxY = action.Point1Y;
                }
                else if (action.Cmd == GUM_ACTION.画直线)
                {
                    maxX = Math.Max(action.Point1X, action.Point2X);
                    maxY = Math.Max(action.Point1Y, action.Point2Y);
                }
                else if (action.Cmd == GUM_ACTION.画圆弧)
                {
                    maxX = action.Point1X + action.Radius;
                    maxY = action.Point1Y + action.Radius;
                }
                else
                {
                    continue;
                }

                maxX += (padding + originX);
                maxY += (padding + originY);

                CalculateDivisor(maxX, maxY, ref div);
            }

            divisor = div;
        }

        private void CalculateDivisor(int maxX, int maxY, ref float div)
        {
            float divisorX = 1;
            float divisorY = 1;
            if (maxX > drawArea.Size.Width)
            {
                divisorX = (float)maxX / (float)drawArea.Size.Width;
            }
            if (maxY > drawArea.Size.Height)
            {
                divisorY = (float)maxY / (float)drawArea.Size.Height;
            }

            if (div < Math.Max(divisorX, divisorY))
            {
                div = Math.Max(divisorX, divisorY);
            }
        }

        private DateTime mDataTime = new DateTime();
        private int mBoardCount;        // 用于工件计数，每当控制返回的currentStep==-1时加1
        private bool mIsBoardCountAdd;  // 用于控制currentStep==-1时只加1一次
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (txtRunningState.Text != "运行")
            {
                return;
            }

            DateTime dataTime = new DateTime();
            dataTime = DateTime.Now;
            TimeSpan timeSpan = new TimeSpan();
            timeSpan = dataTime - mDataTime;
            txtRuntimes.Text = timeSpan.ToString(@"hh\:mm\:ss");

            int index = CGumController.mMashineInfo.currentStep;
            if (index == -1)
            {
                if (!mIsBoardCountAdd)
                {
                    mBoardCount++;
                    mIsBoardCountAdd = true;
                }
            }
            else
            {
                mIsBoardCountAdd = false;
            }
        }

        /// <summary>
        /// 状态变为运行后的处理
        ///  重新开始计时和工件计数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtRunningState_TextChanged(object sender, EventArgs e)
        {
            if (txtRunningState.Text == "运行")
            {
                timer1.Enabled = true;
                txtRuntimes.Text = "";
                mDataTime = DateTime.Now;
                txtBoardCount.Text = "";
                mBoardCount = 0;
            }
        }
    }
}
